#ifndef __OFFMESH_NAVIGATION_MANAGER_H__
#define __OFFMESH_NAVIGATION_MANAGER_H__

#pragma once

#include <INavigationSystem.h>
#include "../MNM/OffGridLinks.h"

class CSmartObject;
class CSmartObjectClass;

//////////////////////////////////////////////////////////////////////////
/// OffMesh Navigation Manager
/// Keeps track of off-mesh navigation objects associated to each navigation mesh
/// and all the smart-objects which can generate off-mesh connections
///
/// Interfaces also with the Navigation System, to update the right objects
/// when meshes are created, updated or deleted
//////////////////////////////////////////////////////////////////////////
class OffMeshNavigationManager
{
private:
	struct SObjectMeshInfo
	{
		SObjectMeshInfo(NavigationMeshID _meshId)
			: meshID(_meshId)
		{

		}

		bool operator==(const NavigationMeshID _meshID)
		{
			return (meshID == _meshID);
		}

		typedef std::vector<MNM::TriangleID>				TTriangleList;
		TTriangleList		triangleList;
		NavigationMeshID	meshID;
	};
	typedef std::vector<SObjectMeshInfo>	TObjectInfo;

public:

	OffMeshNavigationManager(const int offMeshMapSize);

	const MNM::OffMeshNavigation& GetOffMeshNavigationForMesh(const NavigationMeshID& meshID) const;

	//Note: Try to kill this one, outside should never manipulate this
	// Needs to make a lot of code in SmartObjects const correct first...
	MNM::OffMeshNavigation& GetOffMeshNavigationForMesh(const NavigationMeshID& meshID);

	void RegisterSmartObject( CSmartObject* pSmartObject, CSmartObjectClass* pSmartObjectClass );
	void UnregisterSmartObjectForAllClasses( CSmartObject* pSmartObject );
	void UnregisterSmartObject( CSmartObject* pSmartObject, const string& smartObjectClassName );
	
	void RefreshConnections( const NavigationMeshID meshID, const MNM::TileID tileID );
	void Clear();
	void Enable();

	void OnNavigationMeshCreated( const NavigationMeshID& meshID );
	void OnNavigationMeshDestroyed( const NavigationMeshID& meshID );
	void OnNavigationLoadedComplete();

	bool IsObjectLinkedWithNavigationMesh(const EntityId objectId) const;

#if	DEBUG_MNM_ENABLED
	void UpdateEditorDebugHelpers( );
#else
	void UpdateEditorDebugHelpers( ) {};
#endif

private:
	
	bool ObjectRegistered( const EntityId objectId , const string& smartObjectClassName ) const;
	ILINE bool CanRegisterObject() const { return m_objectRegistrationEnabled; };

	// For every navigation mesh, there will be always an off-mesh navigation object
	typedef id_map<uint32, MNM::OffMeshNavigation> TOffMeshMap;
	TOffMeshMap m_offMeshMap;

	MNM::OffMeshNavigation m_emptyOffMeshNavigation;

	// Tracking of objects registered
	// All registered objects are stored here, and some additional data
	// like to witch mesh they belong (only one), or bound triangles/tiles
	typedef VectorMap<uint32, TObjectInfo>				TSOClassInfo;
	typedef std::map<EntityId, TSOClassInfo>			TRegisteredObjects;
	TRegisteredObjects	m_registeredObjects;

	bool m_objectRegistrationEnabled;
};

#endif	//__OFFMESH_NAVIGATION_MANAGER_H__